// 实现这个项目的构建任务
const {src, dest, series, parallel, watch} = require('gulp')
const lint = require('./build/lint')

const minimist = require('minimist')
const useref = require('gulp-useref')
const uglify = require('gulp-uglify')
const postcss = require('gulp-postcss')
const htmlmin = require('gulp-htmlmin')
const beautify = require('gulp-beautify')
const plumber = require('gulp-plumber')
const gulpIf = require('gulp-if')
const imagemin = require('gulp-imagemin')
const del = require('del')

const argv = minimist(process.argv.slice(2))
const browserSync = require('browser-sync')
const bs = browserSync.create()
const isProd = !!(process.env.NODE_ENV === 'production' || argv.production || argv.prod)

const style = () => require('./build/style')(bs, isProd)
const script = () => require('./build/script')(bs, isProd)
const page = () => require('./build/page')(bs, isProd)

const clean = () => {
  return del(['.tmp', 'dist'])
}

const compile = parallel(style, script, page)

const devServer = () => {
  watch('src/assets/styles/*.scss', style)
  watch('src/assets/script/*.js', script)
  watch('src/**/*.html', page)
  watch('src/assets/{fonts,images}/**', bs.reload)
  watch('public/**', bs.reload)

  bs.init({
    server: {
      baseDir: ['.tmp', 'src', 'public']
    },
    plugins: [`bs-html-injector?files[]=.tmp/*.html`],
    notify: false,
    port: argv.port || 2080,
    open: !!argv.open,
    routes: {
      '/node_modules': 'node_modules'
    },
  })
}

const serve = series(compile, devServer)

const ref = () => {
  // https://beautifier.io
  const beautifyOpts = {indent_size: 2, max_preserve_newlines: 1}
  // https://github.com/mishoo/UglifyJS2#minify-options
  const uglifyOpts = {compress: {drop_console: true}}
  // https://cssnano.co/guides/
  const postcssOpts = [cssnano({safe: true, autoprefixer: false})]
  // https://github.com/kangax/html-minifier#options-quick-reference
  const htmlminOpts = {
    collapseWhitespace: true,
    minifyCSS: true,
    minifyJS: true,
    processConditionalComments: true,
    removeComments: true,
    removeEmptyAttributes: true,
    removeScriptTypeAttributes: true,
    removeStyleLinkTypeAttributes: true
  }

  return src('.tmp/**.*.html', {base: '.tmp'})
    .pipe(plumber())
    .pipe(useref({searchPath: ['.tmp', 'src']}))
    .pipe(
      gulpIf(
        /\.js$/,
        gulpIf(isProd, uglify(uglifyOpts), beautify.js(beautifyOpts))
      )
    )
    .pipe(
      gulpIf(
        /\.css$/,
        gulpIf(isProd, postcss(postcssOpts), beautify.css(beautifyOpts))
      )
    )
    .pipe(
      gulpIf(
        /\.html$/,
        gulpIf(isProd, htmlmin(htmlminOpts), beautify.html(beautifyOpts))
      )
    )
    .pipe(dest('dist'))
}

const image = () => {
  return src('src/assets/images/**')
    .pipe(plumber())
    .pipe(gulpIf(isProd, imagemin))
    .pipe(dest('dist'))
}

const font = () => {
  return src('src/assets/font/**')
    .pipe(plumber())
    .pipe(gulpIf(isProd, imagemin))
    .pipe(dest('dist'))
}

const extra = () => {
  return src('public/**', {base: 'public', dot: true})
    .pipe(dest('dist'))
}

const build = series(clean, parallel(series(compile, ref), image, font, extra))

const distServer = ()=> {
  bs.init({
    server: {
      baseDir: ['src']
    },
    port: argv.port || 2080,
    open: !!argv.open,
    routes: {
      '/node_modules': 'node_modules'
    },
  })
}

module.exports = {
  lint,
  compile,
  serve,
  build,
}
